class DoblyNode {
    constructor(data) {
        this.element = data;
        this.previous = null;
        this.next = null;
    }
}

export default class DoublyList {
    /**
     * 头节点
     */
    #head = null;
    /**
     * 尾节点
     */
    #tail = null;
    /**
     * 链表长度
     */
    #count = 0;

    /**
     * 向链表尾部添加元素
     * @param {any} data 
     * @returns true | false
     */
    push(data) {
        const node = new DoblyNode(data);
        if (this.#head === null) {
            this.#head = node;
            this.#tail = node;
        } else {
            this.#tail.next = node;
            node.previous = this.#tail;
            this.#tail = node;
        }

        this.#count++;
        return true
    }

    /**
     * 指定位置插入节点
     * @param {any} data 
     * @param {number} index 
     * @returns true | false
     */
    insert(data, index) {
        if (index >= 0 && index <= this.#count) {
            const node = new DoblyNode(data)
            // 如果插入位置在链表头
            if (index === 0) {
                // 如果当前链表是空链表
                if (this.#head === null) {
                    this.#head = node;
                    this.#tail = node;

                } else { // 如果当前链表非空
                    this.#head.previous = node
                    node.next = this.#head
                    this.#head = node
                }
                this.#count++
                return true

            }
            // 如果插入位置在链表尾
            if (index === this.#count) {
                this.#tail.next = node;
                node.previous = this.#tail;
                this.#tail = node

                this.#count++
                return true
            }

            // 如果插入位置在链表中间
            const currentNode = this.getNodeByIndex(index)
            node.previous = currentNode.previous;
            currentNode.previous.next = node;
            currentNode.previous = node;
            node.next = currentNode;
            this.#count++
            return true

        }
        // 未找到节点，报错
        console.error(`该链表没有对应索引为${index}的节点`)
        return false
    }

    /**
     * 根据索引删除指定节点
     * @param {*} index 
     * @returns {Node} removed node
     */
    removeNodeByIndex(index) {
        if (index >= 0 && index < this.#count) {
            let res = null
            // 如果删除的是链表头
            if (index === 0) {
                // 如果链表只有一个节点
                if (this.#count === 1) {
                    this.#head = null;
                    this.#tail = null;
                } else { // 如果链表不止一个节点
                    res = this.#head
                    this.#head = this.#head.next
                    this.#head.previous = null;
                }
            } else if (index === this.#count - 1) { // 如果删除的是队尾
                res = this.#tail
                this.#tail = this.#tail.previous;
                this.#tail.next = null;
            } else { // 如果删除的是链表的中间位置
                const currentNode = this.getNodeByIndex(index)
                res = currentNode
                currentNode.previous.next = currentNode.next
                currentNode.next.previous = currentNode.previous
            }
            this.#count--;
            return res;
        }
        // 未找到节点，报错
        console.error(`该链表没有对应索引为${index}的节点`);
        return null;
    }

    /**
     * 根据索引查找指定节点
     * @param {string | number} index 
     * @returns {Node} node
     */
    getNodeByIndex(index) {
        if (index >= 0 && index < this.#count) {
            let currentNode = this.#head;
            for (let i = 0; i < index; i++) {
                currentNode = currentNode.next
            }
            return currentNode
        }
        // 未找到节点，报错
        console.error(`该链表没有对应索引为${index}的节点`)
    }

    /**
     * 获取链表头节点
     * @returns List head
     */
    getHead() {
        return this.#headn
    }

    /**
     * 获取链表尾节点
     * @returns List tail
     */
    getTail() {
        return this.#tail
    }

    /**
     * 链表长度
     * @returns list sizes 
     */
    size() {
        return this.#count;
    }
}